home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / daten / astrolog / src / xscreen.c < prev    next >
C/C++ Source or Header  |  1995-08-11  |  58KB  |  2,326 lines

  1. /*                                                               -*- C -*-
  2. ** Astrolog (Version 4.40) File: xscreen.c
  3. **
  4. ** IMPORTANT NOTICE: The graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1995 by Walter D. Pullen
  6. ** (astara@u.washington.edu). Permission is granted to freely use and
  7. ** distribute these routines provided one doesn't sell, restrict, or
  8. ** profit from them in any way. Modification is allowed provided these
  9. ** notices remain with any altered or edited versions of the program.
  10. **
  11. ** The main planetary calculation routines used in this program have
  12. ** been Copyrighted and the core of this program is basically a
  13. ** conversion to C of the routines created by James Neely as listed in
  14. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  15. ** available from Matrix Software. The copyright gives us permission to
  16. ** use the routines for personal use but not to sell them or profit from
  17. ** them in any way.
  18. **
  19. ** The PostScript code within the core graphics routines are programmed
  20. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  21. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  22. **
  23. ** The extended accurate ephemeris databases and formulas are from the
  24. ** calculation routines in the program "Placalc" and are programmed and
  25. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  26. ** (alois@azur.ch). The use of that source code is subject to
  27. ** regulations made by Astrodienst Zurich, and the code is not in the
  28. ** public domain. This copyright notice must not be changed or removed
  29. ** by any user of this program.
  30. **
  31. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  32. ** X Window graphics initially programmed 10/23-29/1991.
  33. ** PostScript graphics initially programmed 11/29-30/1992.
  34. ** Last code change made 1/29/1995.
  35. */
  36.  
  37. /* $VER: $Id: xscreen.c,v 1.4 1995/07/02 22:23:01 tf Exp $ */
  38.  
  39. #include "astrolog.h"
  40.  
  41.  
  42. #ifdef GRAPH
  43. /*
  44. ******************************************************************************
  45. ** Astrolog Icon.
  46. ******************************************************************************
  47. */
  48.  
  49. #if defined(X11) || defined(AMIGA)
  50. /* This information used to define Astrolog's X icon (Rainbow over Third */
  51. /* Eye) is identical to the output format used by the bitmap program.    */
  52. /* You could extract this section and run xsetroot -bitmap on it.        */
  53.  
  54. #define icon_width  63
  55. #define icon_height 32
  56.  
  57. static
  58.  
  59. #ifdef _DCC
  60. __chip
  61. #endif
  62.  
  63. char icon_bits[] = {
  64.  0x00,0x00,0x00,0xa8,0x0a,0x00,0x00,0x00,
  65.  0x00,0x00,0x40,0x55,0x55,0x01,0x00,0x00,
  66.  0x00,0x00,0xa8,0xaa,0xaa,0x0a,0x00,0x00,
  67.  0x00,0x00,0x54,0xf5,0x57,0x15,0x00,0x00,
  68.  0x00,0x80,0xaa,0xaa,0xaa,0xaa,0x00,0x00,
  69.  0x00,0x40,0xd5,0xff,0xff,0x55,0x01,0x00,
  70.  0x00,0xa0,0xaa,0xaa,0xaa,0xaa,0x02,0x00,
  71.  0x00,0x50,0xfd,0xff,0xff,0x5f,0x05,0x00,
  72.  0x00,0xa8,0xaa,0x2a,0xaa,0xaa,0x0a,0x00,
  73.  0x00,0xd4,0xff,0xaf,0xfa,0xff,0x15,0x00,
  74.  0x00,0xaa,0x2a,0x00,0x00,0xaa,0x2a,0x00,
  75.  0x00,0xf5,0xbf,0xaa,0xaa,0xfe,0x57,0x00,
  76.  0x80,0xaa,0x02,0x00,0x00,0xa0,0xaa,0x00,
  77.  0x40,0xfd,0xab,0xfa,0xaf,0xea,0x5f,0x01,
  78.  0xa0,0xaa,0x80,0xff,0xff,0x80,0xaa,0x02,
  79.  0x50,0xff,0xea,0xff,0xff,0xab,0x7f,0x05,
  80.  0xa0,0x2a,0xf0,0xff,0xff,0x07,0xaa,0x02,
  81.  0xd0,0xbf,0xfa,0x0f,0xf8,0xaf,0x7e,0x05,
  82.  0xa8,0x0a,0xfc,0x01,0xc0,0x1f,0xa8,0x0a,
  83.  0xd4,0xaf,0x7e,0x00,0x00,0xbf,0xfa,0x15,
  84.  0xa8,0x0a,0x3f,0x00,0x00,0x7e,0xa8,0x0a,
  85.  0xf4,0xaf,0x1f,0xe0,0x03,0xfc,0xfa,0x15,
  86.  0xaa,0x82,0x0f,0xdc,0x1d,0xf8,0xa0,0x2a,
  87.  0xf4,0xab,0x07,0x23,0x62,0xf0,0xea,0x17,
  88.  0xaa,0xc2,0x87,0x91,0xc4,0xf0,0xa1,0x2a,
  89.  0xf4,0xeb,0xc3,0xd0,0x85,0xe1,0xeb,0x17,
  90.  0xaa,0xe0,0x83,0x91,0xc4,0xe0,0x83,0x2a,
  91.  0xf5,0xeb,0x03,0x23,0x62,0xe0,0xeb,0x57,
  92.  0xaa,0xe0,0x01,0xdc,0x1d,0xc0,0x83,0x2a,
  93.  0xf5,0xeb,0x01,0xe0,0x03,0xc0,0xeb,0x57,
  94.  0xaa,0xe0,0x01,0x00,0x00,0xc0,0x83,0x2a,
  95.  0xfd,0xeb,0x01,0x00,0x00,0xc0,0xeb,0x5f };
  96.  
  97. #ifdef AMIGA
  98. struct Image icon_image = {
  99.   0,                 /* LeftEdge   */
  100.   0,                 /* TopEdge    */
  101.   63,                /* Width      */
  102.   32,                /* Height     */
  103.   1,                 /* Depth      */
  104.   &icon_bits[0],     /* ImageData  */
  105.   0x01,              /* PlanePick  */
  106.   0x00,              /* PlaneOnOff */
  107.   NULL               /* NextImage  */
  108. };
  109. #endif /* AMIGA */
  110.  
  111. #endif /* X11 || AMIGA */
  112.  
  113. /*
  114. ******************************************************************************
  115. ** Interactive Screen Graphics Routines.
  116. ******************************************************************************
  117. */
  118.  
  119. /* Set up all the colors used by the program, i.e. the foreground and   */
  120. /* background colors, and all the colors in the object arrays, based on */
  121. /* whether or not we are in monochrome and/or reverse video mode.       */
  122.  
  123. void InitColorsX()
  124. {
  125.   int i;
  126.  
  127. #ifdef X11
  128.   Colormap cmap;
  129.   XColor xcol;
  130.  
  131.   if (!gi.fFile) {
  132.     cmap = XDefaultColormap(gi.disp, gi.screen);
  133.  
  134.     /* Allocate a color from the present X11 colormap. Given a string like */
  135.     /* "violet", allocate this color and return a value specifying it.     */
  136.  
  137.     for (i = 0; i < 16; i++) 
  138.     {
  139.       XParseColor(gi.disp, cmap, szColorX[i], &xcol);
  140.       XAllocColor(gi.disp, cmap, &xcol);
  141.       rgbind[i] = xcol.pixel;
  142.     }
  143.   }
  144. #endif
  145.  
  146.   /* tf: corrected integer arithmetics with booleans: TRUE does not neccessarily be +1 !! */
  147.  
  148.   gi.kiOn   = kMainA[ (!gs.fInverse) ? 1:0 ]; /*kMainA[!gs.fInverse];*/
  149.   gi.kiOff  = kMainA[gs.fInverse ? 1:0];
  150.   gi.kiLite = gs.fColor ? kMainA[2+ (gs.fInverse ? 1:0)] : gi.kiOn;
  151.   gi.kiGray = gs.fColor ? kMainA[3- (gs.fInverse ? 1:0)] : gi.kiOn;
  152.  
  153.   for (i = 0; i <= 8; i++)          kMainB[i]    = gs.fColor ? kMainA[i]    : gi.kiOn;
  154.   for (i = 0; i <= 7; i++)          kRainbowB[i] = gs.fColor ? kRainbowA[i] : gi.kiOn;
  155.   for (i = 0; i < 4; i++)           kElemB[i]    = gs.fColor ? kElemA[i]    : gi.kiOn;
  156.   for (i = 0; i <= cAspect; i++)    kAspB[i]     = gs.fColor ? kAspA[i]     : gi.kiOn;
  157.   for (i = 0; i <= cObj; i++)       kObjB[i]     = gs.fColor ? kObjA[i]     : gi.kiOn;
  158.  
  159. #if 0 /* debug */
  160.   printf("kMainB[]\n");    for (i = 0; i <= 8; i++)         printf("\t%d\n",kMainB[i]);
  161.   printf("kRainbowB[]\n"); for (i = 0; i <= 7; i++)         printf("\t%d\n",kRainbowB[i]);
  162.   printf("kElemB[]\n");    for (i = 0; i < 4; i++)          printf("\t%d\n",kElemB[i]);
  163.   printf("kAspB[]\n");     for (i = 0; i <= cAspect; i++)   printf("\t%d\n",kAspB[i]);
  164.   printf("kObjB[]\n");     for (i = 0; i <= cObj; i++)      printf("\t%d\n",kObjB[i]);
  165. #endif
  166.  
  167. #ifdef X11
  168.   if (!gi.fFile) 
  169.   {
  170.     XSetBackground(gi.disp, gi.gc,   rgbind[gi.kiOff]);
  171.     XSetForeground(gi.disp, gi.pmgc, rgbind[gi.kiOff]);
  172.   }
  173. #endif
  174. }
  175.  
  176.  
  177. #ifdef ISG
  178. /* This routine opens up and initializes a window and prepares it to be */
  179. /* drawn upon, and gets various information about the display, too.     */
  180.  
  181. void BeginX()
  182. {
  183.  
  184. #ifdef X11
  185.   gi.disp = XOpenDisplay(gs.szDisplay);
  186.  
  187.   if (gi.disp == NULL)
  188.   {
  189.     PrintError("Can't open display.");
  190.     Terminate(tcFatal);
  191.   }
  192.  
  193.   gi.screen = DefaultScreen(gi.disp);
  194.  
  195.   bg = BlackPixel(gi.disp, gi.screen);
  196.   fg = WhitePixel(gi.disp, gi.screen);
  197.  
  198.   hint.x = gi.xOffset; 
  199.   hint.y = gi.yOffset;
  200.  
  201.   hint.width = gs.xWin;
  202.   hint.height = gs.yWin;
  203.  
  204.   hint.min_width = BITMAPX1;  hint.min_height = BITMAPY1;
  205.   hint.max_width = BITMAPX;   hint.max_height = BITMAPY;
  206.  
  207.   hint.flags = PPosition | PSize | PMaxSize | PMinSize;
  208.  
  209. #if FALSE
  210.   wmhint = XGetWMHints(gi.disp, gi.wind);
  211.   wmhint->input = True;
  212.   XSetWMHints(gi.disp, gi.wind, wmhint);
  213. #endif
  214.  
  215.   gi.depth = DefaultDepth(gi.disp, gi.screen);
  216.  
  217.   if (gi.depth < 5)
  218.   {
  219.     gi.fMono = fTrue;      /* Is this a monochrome monitor? */
  220.     gs.fColor = fFalse;
  221.   }
  222.  
  223.   gi.root = RootWindow(gi.disp, gi.screen);
  224.  
  225.   if (gs.fRoot)
  226.     gi.wind = gi.root;     /* If -XB in effect, we'll use the root window. */
  227.  
  228.   else
  229.     gi.wind = XCreateSimpleWindow(gi.disp, DefaultRootWindow(gi.disp),
  230.       hint.x, hint.y, hint.width, hint.height, 5, fg, bg);
  231.  
  232.   gi.pmap = XCreatePixmap(gi.disp, gi.wind, gs.xWin, gs.yWin, gi.depth);
  233.   gi.icon = XCreateBitmapFromData(gi.disp, DefaultRootWindow(gi.disp), icon_bits, icon_width, icon_height);
  234.  
  235.   if (!gs.fRoot)
  236.     XSetStandardProperties(gi.disp, gi.wind, szAppName, szAppName, gi.icon, (char **)xkey, 0, &hint);
  237.  
  238.   /* We have two graphics workareas. One is what the user currently sees in */
  239.   /* the window, and the other is what we are currently drawing on. When    */
  240.   /* done, we can quickly copy this to the viewport for a smooth look.      */
  241.  
  242.   gi.gc = XCreateGC(gi.disp, gi.wind, 0, 0);
  243.  
  244.   XSetGraphicsExposures(gi.disp, gi.gc, 0);
  245.   gi.pmgc = XCreateGC(gi.disp, gi.wind, 0, 0);
  246.  
  247.   InitColorsX();                           /* Go set up colors. */
  248.  
  249.   if (!gs.fRoot)
  250.     XSelectInput(gi.disp, gi.wind, KeyPressMask | StructureNotifyMask
  251.                                                 | ExposureMask
  252.                                                 | ButtonPressMask
  253.                                                 | ButtonReleaseMask
  254.                                                 | ButtonMotionMask  );
  255.  
  256.   XMapRaised(gi.disp, gi.wind);
  257.   XSync(gi.disp, 0);
  258.   XFillRectangle(gi.disp, gi.pmap, gi.pmgc, 0, 0, gs.xWin, gs.yWin);
  259. #endif /* X11 */
  260.  
  261. #ifdef MSG
  262.   if (!FValidResmode(gi.nRes))    /* Initialize graphics mode to hi-res. */
  263.     gi.nRes = gs.nResHi;
  264.  
  265.   _setvideomode(gi.nRes);
  266.  
  267.   if (_grstatus())
  268.   {
  269.     PrintError("Can't enter graphics mode.");
  270.     Terminate(tcFatal);
  271.   }
  272.  
  273.   _getvideoconfig((struct videoconfig far *) &gi.cfg);
  274.  
  275.   if (gi.cfg.numcolors < 16)
  276.   {
  277.     gi.fMono  = fTrue;
  278.     gs.fColor = fFalse;
  279.   }
  280.   _remapallpalette((long FAR *) rgb);
  281.   _setactivepage(0);
  282.   _setvisualpage(0);
  283.   InitColorsX();
  284.  
  285. #ifdef MOUSE
  286.   MouseInit(xPcScreen, yPcScreen);
  287. #endif
  288.  
  289.   /* Make sure we reset textrows upon restart. */
  290.   gs.nTextRows = abs(gs.nTextRows);
  291. #endif /* MSG */
  292.  
  293. #ifdef BGI
  294.   int i;
  295.   static struct palettetype pal;
  296.  
  297.   if ( !FValidResmode(gi.nRes) )    /* Initialize graphics mode to hi-res. */
  298.     gi.nRes = gs.nResHi;
  299.  
  300.   if (!gi.fLoaded) 
  301.   {
  302.     registerfarbgidriver(ATT_driver_far);      /* attf.obj     */
  303.     registerfarbgidriver(CGA_driver_far);      /* cgaf.obj     */
  304.     registerfarbgidriver(EGAVGA_driver_far);   /* egavgaf.obj  */
  305.     registerfarbgidriver(Herc_driver_far);     /* hercf.obj    */
  306.     registerfarbgidriver(IBM8514_driver_far);  /* ibm8514f.obj */
  307.     registerfarbgidriver(PC3270_driver_far);   /* pc3270f.obj  */
  308.     gi.nDriver = DETECT;
  309.     initgraph(&gi.nDriver, &gi.nGraph, "");
  310.     gi.fLoaded = fTrue;
  311.   }
  312.  
  313.   if (gi.nRes <= 0) {
  314.     switch (gi.nDriver) {
  315.     case CGA:      gi.nGraph = CGAHI;      break;
  316.     case MCGA:     gi.nGraph = MCGAHI;     break;
  317.     case EGA:      gi.nGraph = EGAHI;      break;
  318.     case EGA64:    gi.nGraph = EGA64HI;    break;
  319.     case EGAMONO:  gi.nGraph = EGAMONOHI;  break;
  320.     case HERCMONO: gi.nGraph = HERCMONOHI; break;
  321.     case ATT400:   gi.nGraph = ATT400HI;   break;
  322.     case VGA:      gi.nGraph = VGAHI;      break;
  323.     case PC3270:   gi.nGraph = PC3270HI;   break;
  324.     case IBM8514:  gi.nGraph = IBM8514HI;  break;
  325.     default:       gi.nGraph = 0;
  326.     }
  327.   }
  328.   else /* gi.nRes > 0 */
  329.   {
  330.     switch (gi.nDriver) {
  331.     case CGA:      gi.nGraph = CGAHI;      break;
  332.     case MCGA:     gi.nGraph = MCGAHI;     break;
  333.     case EGA:      gi.nGraph = EGAHI;      break;
  334.     case EGA64:    gi.nGraph = EGA64HI;    break;
  335.     case EGAMONO:  gi.nGraph = EGAMONOHI;  break;
  336.     case HERCMONO: gi.nGraph = HERCMONOHI; break;
  337.     case ATT400:   gi.nGraph = ATT400HI;   break;
  338.     case VGA:      gi.nGraph = VGAMED;     break;
  339.     case PC3270:   gi.nGraph = PC3270HI;   break;
  340.     case IBM8514:  gi.nGraph = IBM8514LO;  break;
  341.     default:       gi.nGraph = 0;
  342.     }
  343.   }
  344.  
  345.   setgraphmode(gi.nGraph);
  346.  
  347.   if( graphresult() )
  348.   {
  349.     PrintError("Can't enter graphics mode.");
  350.     Terminate(tcFatal);
  351.   }
  352.  
  353.   gi.nPages = 1 + (gi.nDriver == HERCMONO || (gi.nDriver == VGA && gi.nGraph != VGAHI) || gi.nDriver == EGA);
  354.  
  355.   if (getmaxcolor()+1 < 16) 
  356.   {
  357.     gi.fMono  = fTrue;
  358.     gs.fColor = fFalse;
  359.   }
  360.   getpalette(&pal);
  361.  
  362.   for (i = 0; i < pal.size; i++)
  363.     pal.colors[i] = (char)rgb[i];
  364.  
  365.   setallpalette(&pal);
  366.   setactivepage(0);
  367.   setvisualpage(0);
  368.   gi.nPageCur = 0;
  369.   InitColorsX();
  370.  
  371. #ifdef MOUSE
  372.   MouseInit(xPcScreen, yPcScreen);
  373. #endif
  374.  
  375.   /* Make sure we reset textrows upon restart. */
  376.   gs.nTextRows = abs(gs.nTextRows);
  377.  
  378. #endif /* BGI */
  379.  
  380. #ifdef AMIGA
  381.   if( AmigaDisplayInit() )
  382.   {
  383.     AmigaDisplayExit();
  384.     PrintError("Can't open display.");
  385.     Terminate(tcFatal);
  386.   }
  387.  InitColorsX();
  388. #endif /* AMIGA */
  389. }
  390.  
  391.  
  392. /* Add a certain amount of time to the current hour/day/month/year quantity */
  393. /* defining the present chart. This is used by the chart animation feature. */
  394. /* We can add or subtract anywhere from 1 to 9 seconds, minutes, hours,     */
  395. /* days, months, years, decades, centuries, or millenia in any one call.    */
  396. /* This is mainly just addition to the appropriate quantity, but we have    */
  397. /* to check for overflows, e.g. Dec 30 + 3 days = Jan 2 of Current year + 1 */
  398.  
  399. void AddTime(mode, toadd)
  400. int mode, toadd;
  401. {
  402.   int d;
  403.   real h, m;
  404.  
  405.   if ( !FBetween(mode, 1, 9) )
  406.     mode = 4;
  407.  
  408.   h = RFloor(TT);
  409.   m = RFract(TT)*100.0;
  410.  
  411.   if (mode == 1)      m += 1.0/60.0*(real)toadd;    /* Add seconds. */
  412.   else if (mode == 2) m += (real)toadd;             /* add minutes. */
  413.  
  414.   /* Add hours, either naturally or if minute value overflowed. */
  415.  
  416.   if (m < 0.0 || m >= 60.0 || mode == 3) 
  417.   {
  418.     if (m >= 60.0)
  419.     {
  420.       m -= 60.0; toadd = NSgn(toadd);
  421.     }
  422.     else if (m < 0.0)
  423.     {
  424.       m += 60.0; toadd = NSgn(toadd);
  425.     }
  426.     h += (real)toadd;
  427.   }
  428.  
  429.   /* Add days, either naturally or if hour value overflowed. */
  430.  
  431.   if (h >= 24.0 || h < 0.0 || mode == 4)
  432.   {
  433.     if (h >= 24.0) 
  434.     {
  435.       h -= 24.0; toadd = NSgn(toadd);
  436.     } 
  437.     else if (h < 0.0)
  438.     {
  439.       h += 24.0; toadd = NSgn(toadd);
  440.     }
  441.     DD = AddDay(MM, DD, YY, toadd);
  442.   }
  443.  
  444.   /* Add months, either naturally or if day value overflowed. */
  445.  
  446.   if (DD > (d = DayInMonth(MM, YY)) || DD < 1 || mode == 5) {
  447.     if (DD > d) 
  448.     {
  449.       DD -= d; toadd = NSgn(toadd);
  450.     }
  451.     else if (DD < 1)
  452.     {
  453.       DD += DayInMonth(Mod12(MM - 1), YY);
  454.       toadd = NSgn(toadd);
  455.     }
  456.     MM += toadd;
  457.   }
  458.  
  459.   /* Add years, either naturally or if month value overflowed. */
  460.  
  461.   if (MM > 12 || MM < 1 || mode == 6) 
  462.   {
  463.     if (MM > 12) 
  464.     {
  465.       MM -= 12; toadd = NSgn(toadd);
  466.     } 
  467.  
  468.     else if (MM < 1) 
  469.     {
  470.       MM += 12; toadd = NSgn(toadd);
  471.     }
  472.     YY += toadd;
  473.   }
  474.  
  475.   if (mode == 7)
  476.     YY += 10 * toadd;      /* Add decades.   */
  477.  
  478.   else if (mode == 8)
  479.     YY += 100 * toadd;     /* Add centuries. */
  480.  
  481.   else if (mode == 9)
  482.     YY += 1000 * toadd;    /* Add millenia.  */
  483.  
  484.   TT = h+m/100.0;          /* Recalibrate hour time. */
  485. }
  486.  
  487.  
  488. /* Animate the current chart based on the given values indicating how much  */
  489. /* to update by. We update and recast the current chart info appropriately. */
  490.  
  491. void Animate(mode, toadd)
  492. int mode, toadd;
  493. {
  494.   if (gi.nMode == gWorldMap || gi.nMode == gGlobe || gi.nMode == gPolar)
  495.   {
  496.     gs.nRot += toadd;
  497.  
  498.     if (gs.nRot >= nDegMax)     /* For animating globe display, add */
  499.       gs.nRot -= nDegMax;       /* in appropriate degree value.     */
  500.     else if (gs.nRot < 0)
  501.       gs.nRot += nDegMax;
  502.   }
  503.   else  
  504.   {
  505.     if (mode == 10) 
  506.     {
  507. #ifdef TIME
  508.       /* For the continuous chart update to present moment */
  509.       /* animation mode, go get whatever time it is now.   */
  510.       FInputData(szNowCore);
  511. #else
  512.       ciCore = ciMain;
  513.       AddTime(1, toadd);
  514. #endif
  515.     } 
  516.     else /* Otherwise add on appropriate time vector to chart info. */
  517.     {
  518.       ciCore = ciMain;
  519.       AddTime(mode, toadd);
  520.     }
  521.     ciMain = ciCore;
  522.  
  523.     if (us.nRel)
  524.       CastRelation(fFalse);
  525.     else
  526.       CastChart(fTrue);
  527.   }
  528. }
  529.  
  530.  
  531. /* This routine exits graphics mode, prompts the user for a set of command */
  532. /* switches, processes them, and returns to the previous graphics with the */
  533. /* new settings in effect, allowing one to change most any setting without */
  534. /* having to lose their graphics state or fall way back to a -Q loop.      */
  535.  
  536. void CommandLineX()
  537. {
  538.   char szCommandLine[cchSzMax], *rgsz[MAXSWITCHES];
  539.   int argc, fT, fPause = fFalse;
  540.  
  541.   ciCore = ciMain;
  542.  
  543. #ifdef MSG
  544.   _setvideomode(_DEFAULTMODE);
  545.   _settextrows(gs.nTextRows);
  546. #endif
  547.  
  548. #ifdef BGI
  549.   restorecrtmode();
  550.   if (gs.nTextRows > 25)
  551.     textmode(C4350);
  552. #endif
  553.  
  554. #ifdef AMIGA
  555.   EndX();
  556. #endif /* AMIGA */
  557.  
  558.   fT = us.fLoop; us.fLoop = fTrue;
  559.   argc = NPromptSwitches(szCommandLine, rgsz);
  560.   is.cchRow = 0;
  561.   is.fSzInteract = fTrue;
  562.  
  563.   if (!FProcessSwitches(argc, rgsz))
  564.     fPause = fTrue;
  565.  
  566.   else
  567.   {
  568.     is.fMult = fFalse;
  569.     FPrintTables();
  570.  
  571.     if (is.fMult)
  572.     {
  573.       ClearB((lpbyte)&us.fCredit,
  574.         (int)((lpbyte)&us.fLoop - (lpbyte)&us.fCredit));
  575.       fPause = fTrue;
  576.     }
  577.   }
  578.  
  579. #if defined(PCG) || defined(AMIGA)
  580.  
  581.   /* Pause for the user if there was either an error processing the    */
  582.   /* switches, or one of the informational text tables was brought up. */
  583.  
  584.   if(fPause)
  585.   {
  586.     AnsiColor(kDefault);
  587.     is.cchRow = 0;
  588.     PrintSz("Press any key to return to graphics.\n");
  589.  
  590. #ifdef PCG
  591.     while (!kbhit())
  592.       ;
  593.     getch();
  594. #endif
  595.  
  596. #ifdef AMIGA
  597.     (void)getkey();
  598. #endif
  599.   }
  600. #endif
  601.  
  602.   is.fSzInteract = fFalse;
  603.   us.fLoop = fT;
  604.   ciMain = ciCore;
  605.   BeginX();
  606. }
  607.  
  608.  
  609. /* Given two chart size values, adjust them such that the chart will look */
  610. /* "square". We round the higher value down and check certain conditions. */
  611.  
  612. void SquareX(x, y, force)
  613. int *x, *y, force;
  614. {
  615.   if (!force && !fSquare)    /* Unless we want to force a square, realize */
  616.     return;                  /* that some charts look better rectangular. */
  617.   if (*x > *y)
  618.     *x = *y;
  619.   else
  620.     *y = *x;
  621.  
  622. #ifdef PCG
  623.   if (FEgaRes(gi.nRes))         /* Scale horizontal size if we're in a PC */
  624.     *x = VgaFromEga(*x);        /* graphics mode without "square" pixels. */
  625.   else if (FCgaRes(gi.nRes))
  626.     *x = VgaFromCga(*x);
  627. #endif
  628.  
  629.   if (fSidebar)      /* Take into account chart's sidebar, if any. */
  630.     *x += xSideT;
  631. }
  632.  
  633.  
  634. /* This routine gets called after graphics are brought up and displayed     */
  635. /* on the screen. It loops, processing key presses, mouse clicks, etc, that */
  636. /* the window receives, until the user specifies they want to exit program. */
  637.  
  638. void InteractX()
  639. {
  640. #ifdef X11
  641.   char sz[cchSzDef];
  642.   XEvent xevent;
  643.   KeySym keysym;
  644.   int fResize = fFalse, fRedraw = fTrue;
  645. #endif
  646.  
  647. #ifdef PCG
  648. #ifdef MOUSE
  649.   int eventx, eventy, eventbtn;
  650. #endif
  651.   int fResize = fTrue, fRedraw = fFalse;
  652. #endif /* PCG */
  653.  
  654. #ifdef AMIGA
  655.   int fResize = fFalse, fRedraw = fTrue;
  656.   int fMouseDown= fFalse;
  657.  
  658.   /*
  659.    *  Since some chart windows need a certain size, we have save the initial
  660.    *  window dimensions.  This might be a general astrolog problem, however I
  661.    *  fixed it for Amiga only since I'm not sure.
  662.    */
  663.  
  664.   int gs_xWin= gs.xWin,
  665.       gs_yWin= gs.yWin;
  666. #endif
  667.  
  668.   int fBreak = fFalse,
  669.       fPause = fFalse,
  670.       fCast = fFalse,
  671.       xcorner = 7,
  672.       mousex = -1,
  673.       mousey = -1,
  674.       buttonx = -1,
  675.       buttony = -1,
  676.       dir = 1,
  677.       length, key, i;
  678.  
  679.   bool fT;
  680.   KI coldrw = gi.kiLite;
  681.  
  682.   neg(gs.nAnim);
  683.  
  684.   /*
  685.    *  interaction loop
  686.    */
  687.  
  688.   while (!fBreak)
  689.   {
  690.  
  691. #ifdef AMIGA
  692.     if(gs.xWin != gs_xWin) { gs.xWin= gs_xWin; fResize= fTrue; }
  693.     if(gs.yWin != gs_yWin) { gs.yWin= gs_yWin; fResize= fTrue; }
  694. #endif
  695.  
  696.     gi.nScale = gs.nScale/100;
  697.  
  698.     /* Some chart windows, like the world maps and aspect grids, should */
  699.     /* always be a certian size, so correct if a resize was attempted.  */
  700.  
  701.     if (fMap)
  702.     {
  703.       length = nDegMax * gi.nScale;
  704.  
  705.       if (gs.xWin != length)
  706.       {
  707.         gs.xWin = length;
  708.         fResize = fTrue;
  709.       }
  710.  
  711.       length = nDegHalf*gi.nScale;
  712.  
  713.       if (gs.yWin != length)
  714.       {
  715.         gs.yWin = length;
  716.         fResize = fTrue;
  717.       }
  718.     }
  719.  
  720.     else if (gi.nMode == gGrid)
  721.     {
  722.       if (gs.xWin !=
  723.         (length = (gs.nGridCell + (us.nRel <= rcDual)) * CELLSIZE*gi.nScale+1))
  724.       {
  725.         gs.xWin = length;
  726.         fResize = fTrue;
  727.       }
  728.  
  729.       if (gs.yWin != length)
  730.       {
  731.         gs.yWin = length;
  732.         fResize = fTrue;
  733.       }
  734.     }
  735.  
  736.     /* Make sure the window isn't too large or too small. */
  737.  
  738.     else
  739.     {
  740.       if (gs.xWin < BITMAPX1) 
  741.       {
  742.         gs.xWin = BITMAPX1;
  743.         fResize = fTrue;
  744.       }
  745.  
  746.       else if (gs.xWin > BITMAPX)
  747.       {
  748.         gs.xWin = BITMAPX;
  749.         fResize = fTrue;
  750.       }
  751.  
  752.       if (gs.yWin < BITMAPY1) 
  753.       {
  754.         gs.yWin = BITMAPY1;
  755.         fResize = fTrue;
  756.       }
  757.       else if (gs.yWin > BITMAPY)
  758.       {
  759.         gs.yWin = BITMAPY;
  760.         fResize = fTrue;
  761.       }
  762.     }
  763.  
  764.     /* If in animation mode, ensure we are in the flicker free resolution. */
  765.  
  766.     if (gs.nAnim < 0) 
  767.     {
  768.       neg(gs.nAnim);
  769.  
  770. #ifdef PCG
  771.       if (gi.nRes == gs.nResHi && !gs.fJetTrail)
  772.       {
  773.         gi.nRes = gs.nResLo;
  774.         BeginX();
  775.         gs.xWin = xPcScreen;
  776.         gs.yWin = yPcScreen;
  777.         SquareX(&gs.xWin, &gs.yWin, fFalse);
  778.         fResize = fTrue;
  779.       }
  780. #endif
  781.     }
  782.  
  783. #ifdef AMIGA
  784.     /* toggle double buffering depending on `gs.nAnim' */
  785.  
  786.     if( (gs.nAnim && !gi.paging) || (!gs.nAnim && gi.paging) )
  787.       AmigaDisplayPaging();
  788. #endif
  789.  
  790.     /* Physically resize window if we've changed the size parameters. */
  791.  
  792.     if (fResize)
  793.     {
  794.       fResize = fFalse;
  795.  
  796. #ifdef X11
  797.       XResizeWindow(gi.disp, gi.wind, gs.xWin, gs.yWin);
  798.       XFreePixmap(gi.disp, gi.pmap);
  799.       gi.pmap = XCreatePixmap(gi.disp, gi.wind, gs.xWin, gs.yWin, gi.depth);
  800. #endif
  801.  
  802. #ifdef PCG
  803.       if (xPcScreen > gs.xWin)
  804.         gi.xOffset = (xPcScreen - gs.xWin) / 2;
  805.  
  806.       else
  807.       {
  808.         if (xcorner % 3 == 1)
  809.           gi.xOffset = 0;
  810.         else if (xcorner % 3 == 0)
  811.           gi.xOffset = -gs.xWin + xPcScreen;
  812.         else
  813.           gi.xOffset = -(gs.xWin - xPcScreen) / 2;
  814.       }
  815.  
  816.       if (yPcScreen > gs.yWin)
  817.         gi.yOffset = (yPcScreen - gs.yWin) / 2;
  818.  
  819.       else
  820.       {
  821.         if (xcorner > 6)
  822.           gi.yOffset = 0;
  823.         else if (xcorner < 4)
  824.           gi.yOffset = -gs.yWin + yPcScreen;
  825.         else
  826.           gi.yOffset = -(gs.yWin - yPcScreen) / 2;
  827.       }
  828. #endif /* PCG */
  829.  
  830. #ifdef AMIGA
  831.       if( AmigaDisplayResize(gs.xWin, gs.yWin) != 0 )
  832.       {
  833.         PrintError("Can't resize display.");
  834.         Terminate(tcFatal);
  835.         fBreak= fTrue;
  836.         break;
  837.       }
  838. #endif /* AMIGA */
  839.  
  840.  
  841.       fRedraw = fTrue;
  842.     }
  843.  
  844.     /* Recast chart if the chart information has changed any. */
  845.  
  846.     if (fCast)
  847.     {
  848.       fCast = fFalse;
  849.       ciCore = ciMain;
  850.  
  851.       if (us.nRel)
  852.         CastRelation(fFalse);
  853.       else
  854.         CastChart(fTrue);
  855.  
  856.       fRedraw = fTrue;
  857.     }
  858.  
  859.     if (gs.nAnim && !fPause)
  860.       fRedraw = fTrue;
  861.  
  862.     /* Update the screen if anything has changed since last time around. */
  863.  
  864.     if (fRedraw)
  865.     {
  866.       fRedraw = fFalse;
  867.  
  868.       /* If we're in animation mode, change the chart info appropriately. */
  869.  
  870.       if (gs.nAnim && !fPause)
  871.         Animate(gs.nAnim, dir);
  872.  
  873.       /* Clear the screen and set up a buffer to draw in. */
  874.  
  875. #ifdef X11
  876.       XFillRectangle(gi.disp, gi.pmap, gi.pmgc, 0, 0, gs.xWin, gs.yWin);
  877. #endif
  878.  
  879.  
  880. #ifdef PCG
  881.  
  882. #if defined(PC) && defined(MOUSE)
  883.       MouseShow(fFalse);
  884. #endif /* PC & MOUSE */
  885.  
  886. #ifdef MSG
  887.       if (gi.cfg.numvideopages > 1)
  888.         _setactivepage(_getactivepage() == gs.fJetTrail);
  889.  
  890. #else /* !MSG */
  891.       if (gi.nPages > 1)
  892.       {
  893.         gi.nPageCur = (gi.nPageCur == gs.fJetTrail);
  894.         setactivepage(gi.nPageCur);
  895.       }
  896. #endif /* MSG */
  897.  
  898. #endif /* PCG */
  899.  
  900. #ifdef AMIGA
  901.       if(!gs.fJetTrail)
  902.         AmigaClearScreen();
  903. #endif /* AMIGA */
  904.  
  905.       DrawChartX();
  906.  
  907.       /* Make the drawn chart visible in the current screen buffer. */
  908.  
  909. #ifdef X11
  910.       XSync(gi.disp, 0);
  911.       XCopyArea(gi.disp, gi.pmap, gi.wind, gi.gc, 0, 0, gs.xWin, gs.yWin, 0, 0);
  912. #else /* PCG */
  913.  
  914. #ifdef MSG
  915.       if (gi.cfg.numvideopages > 1)
  916.         _setvisualpage(_getactivepage());
  917. #endif /* MSG */
  918.  
  919.  
  920. #ifdef PCG
  921.       if (gi.nPages > 1)
  922.         setvisualpage(gi.nPageCur);
  923. #endif /* PCG */
  924.  
  925. #if defined(PC) && defined(MOUSE)
  926.       if (!gs.nAnim || fPause)
  927.         MouseShow(fTrue);
  928. #endif /* PC && MOUSE */
  929.  
  930. #endif /* PCG */
  931.  
  932. #ifdef AMIGA
  933.       AmigaDisplayUpdate();
  934. #endif /* AMIGA */
  935.  
  936.     }  /* fRedraw */
  937.  
  938.     /* Now process what's on the event queue, i.e. any keys pressed, etc. */
  939.  
  940. #ifdef X11
  941.     if (XEventsQueued(gi.disp, QueuedAfterFlush /*QueuedAfterReading*/) || !gs.nAnim || fPause)
  942.     {
  943.       XNextEvent(gi.disp, &xevent);
  944.  
  945.       /* Restore what's on window if a part of it gets uncovered. */
  946.  
  947.       if (xevent.type == Expose && xevent.xexpose.count == 0) 
  948.       {
  949.         XSync(gi.disp, 0);
  950.         XCopyArea(gi.disp, gi.pmap, gi.wind, gi.gc, 0, 0, gs.xWin, gs.yWin, 0, 0);
  951.       }
  952.       switch (xevent.type) {
  953.  
  954.       /* Check for a manual resize of window by user. */
  955.  
  956.       case ConfigureNotify:
  957.         gs.xWin = xevent.xconfigure.width;
  958.         gs.yWin = xevent.xconfigure.height;
  959.         XFreePixmap(gi.disp, gi.pmap);
  960.         gi.pmap = XCreatePixmap(gi.disp, gi.wind, gs.xWin, gs.yWin, gi.depth);
  961.         fRedraw = fTrue;
  962.         break;
  963.  
  964.       case MappingNotify:
  965.         XRefreshKeyboardMapping((XMappingEvent *)&xevent);
  966.         break;
  967.  
  968. #ifdef MOUSE
  969.       /* Process any mouse buttons the user pressed. */
  970.  
  971.       case ButtonPress:
  972.         mousex = xevent.xbutton.x; mousey = xevent.xbutton.y;
  973.  
  974.         if (xevent.xbutton.button == Button1)
  975.         {
  976.           DrawColor(gi.kiLite);
  977.           DrawPoint(mousex, mousey);
  978.           XSync(gi.disp, 0);
  979.           XCopyArea(gi.disp, gi.pmap, gi.wind, gi.gc, 0, 0, gs.xWin, gs.yWin, 0, 0);
  980.         }
  981.         else if(xevent.xbutton.button == Button2 &&
  982.           (gi.nMode == gAstroGraph || gi.nMode == gWorldMap) && gs.nRot == 0)
  983.         {
  984.           Lon = DegToDec(rDegHalf - (real)(xevent.xbutton.x-1)/(real)(gs.xWin-2)*rDegMax);
  985.           Lat = DegToDec(rDegQuad - (real)(xevent.xbutton.y-1)/(real)(gs.yWin-2)*181.0);
  986.           sprintf(sz, "Mouse is at %s.", SzLocation(Lon, Lat));
  987.           PrintNotice(sz);
  988.         }
  989.         else if (xevent.xbutton.button == Button3)
  990.           fBreak = fTrue;
  991.         break;
  992.  
  993.       /* Check for user dragging any of the mouse buttons across window. */
  994.  
  995.       case MotionNotify:
  996.         DrawColor(coldrw);
  997.         DrawLine(mousex, mousey, xevent.xbutton.x, xevent.xbutton.y);
  998.         XSync(gi.disp, 0);
  999.         XCopyArea(gi.disp, gi.pmap, gi.wind, gi.gc, 0, 0, gs.xWin, gs.yWin, 0, 0);
  1000.         mousex = xevent.xbutton.x; mousey = xevent.xbutton.y;
  1001.         break;
  1002.  
  1003. #endif /* MOUSE */
  1004.  
  1005.       /* Process any keys user pressed in window. */
  1006.  
  1007.       case KeyPress:
  1008.         length = XLookupString((XKeyEvent *)&xevent, xkey, 10, &keysym, 0);
  1009.         if (length == 1) {
  1010.           key = xkey[0];
  1011.  
  1012. #endif /* X11 */
  1013.  
  1014.       /*
  1015.        *  Get events on PC
  1016.        */
  1017.  
  1018. #ifdef PCG
  1019. #ifdef MOUSE
  1020.       if ((!gs.nAnim || fPause) && MouseStatus(&eventx, &eventy, &eventbtn))
  1021.       {
  1022.         /* If the left button is down, draw on the screen. */
  1023.  
  1024.         if (eventbtn == mfLeft && mousex >= 0)
  1025.         {
  1026.           MouseShow(fFalse);
  1027.           DrawColor(coldrw);
  1028.           PcMoveTo(mousex, mousey);
  1029.           buttonx = eventx; buttony = eventy;
  1030.           PcLineTo(buttonx, buttony);
  1031.         }
  1032.  
  1033.         /* If the right button is down, change the default location. */
  1034.  
  1035.         else if (eventbtn == mfRight) 
  1036.         {
  1037.           if (fMap && gs.nRot == 0 && !gs.fConstel && !gs.fMollewide)
  1038.           {
  1039.             Lon = rDegHalf-(real)(eventx-gi.xOffset)/(real)(gs.xWin-2)*rDegMax;
  1040.  
  1041.             if (Lon < -rDegHalf)      Lon = -rDegHalf;
  1042.             else if (Lon > rDegHalf)  Lon =  rDegHalf;
  1043.  
  1044.             Lat =  rDegQuad-(real)(eventy-gi.yOffset)/(real)(gs.yWin-2)*181.0;
  1045.  
  1046.             if (Lat < -rDegQuad)      Lat = -rDegQuad;
  1047.             else if (Lat > rDegQuad)  Lat =  rDegQuad;
  1048.  
  1049.             fCast = fTrue;
  1050.           }
  1051.  
  1052.           /* Right button means draw lines if not in a world map mode. */
  1053.  
  1054.           else if (buttonx >= 0)
  1055.           {
  1056.             MouseShow(fFalse);
  1057.             DrawColor(coldrw);
  1058.             PcMoveTo(buttonx, buttony);
  1059.             PcLineTo(eventx, eventy);
  1060.           }
  1061.         }
  1062.  
  1063.         /* Middle button (which most PC's don't have) means exit program. */
  1064.  
  1065.         else if (eventbtn == mfMiddle)
  1066.           fBreak = fTrue;
  1067.  
  1068.         mousex = eventx; mousey = eventy;
  1069.         MouseShow(fTrue);
  1070.       } else
  1071. #endif /* MOUSE */
  1072.  
  1073.         if (kbhit())
  1074.         {
  1075.           key = getch();
  1076.  
  1077. #endif /* PCG */
  1078.  
  1079.         /*
  1080.          *  Get events on Amiga systems
  1081.          */
  1082.  
  1083. #ifdef AMIGA
  1084.  
  1085. #ifdef MUIGUI
  1086.         key= AmigaDisplayInteract();
  1087.  
  1088. #else /* MUIGUI */
  1089.  
  1090.         /*{ key = getkey();*/
  1091.  
  1092.         key= '\0';  /* undefined = no keypress */
  1093.  
  1094.         {
  1095.           struct Window *w= gi.win;
  1096.           struct IntuiMessage *imsg;
  1097.           ULONG class;
  1098.           USHORT code;
  1099.  
  1100.           /* as long as we don't have any events to export... */
  1101.  
  1102.           while( (key=='\0') && !fBreak && !fResize )
  1103.           {
  1104.             ULONG sig= Wait( SIGBREAKF_CTRL_C | (1L<<w->UserPort->mp_SigBit) );
  1105.  
  1106.             if( sig & SIGBREAKF_CTRL_C )
  1107.               fBreak= fTrue;
  1108.  
  1109.             if( sig & (1L<<w->UserPort->mp_SigBit) )
  1110.               while( (imsg=(struct IntuiMessage *)GetMsg(w->UserPort)) )
  1111.             {
  1112.               class  = imsg->Class;
  1113.               code   = imsg->Code;
  1114.  
  1115.               mousex = (int)(imsg->MouseX);
  1116.               mousey = (int)(imsg->MouseY);
  1117.  
  1118.               ReplyMsg((struct Message *)imsg);
  1119.  
  1120.               switch(class)
  1121.               {
  1122.                 case CLOSEWINDOW:
  1123.                   fBreak= fTrue;
  1124.                   fMouseDown= fFalse;
  1125.                   break;
  1126.  
  1127.                 case VANILLAKEY:
  1128.                   /* the key code is handled at label LSwitch: */
  1129.  
  1130.                   key= (int)code;
  1131.                   fMouseDown= fFalse;
  1132.                   break;
  1133.  
  1134.                 case MOUSEBUTTONS:
  1135.                   if(code==SELECTDOWN)
  1136.                   {
  1137.                     buttonx= mousex;
  1138.                     buttony= mousey;
  1139.  
  1140.                     DrawColor(coldrw);
  1141.                     DrawPoint(mousex,mousey);
  1142.  
  1143.                     fMouseDown= fTrue;
  1144.                   }
  1145.                   else if(code==SELECTUP) /* well, what else can it be? */
  1146.                   {
  1147.                     fMouseDown= fFalse;
  1148.                   }
  1149.                   break;
  1150.  
  1151.                 case MOUSEMOVE:
  1152.                   /* we already initialized mousex and mousey */
  1153.  
  1154.                   if(fMouseDown==fTrue)
  1155.                   {
  1156.                     DrawColor(coldrw);
  1157.                     DrawPoint(mousex,mousey);
  1158.                   }
  1159.                   break;
  1160.  
  1161.                 case NEWSIZE:
  1162.                   {
  1163.                     int xmin= (int)(w->BorderLeft);
  1164.                     int ymin= (int)(w->BorderTop);
  1165.                     int xmax= (int)(w->Width  - w->BorderRight  - 1);
  1166.                     int ymax= (int)(w->Height - w->BorderBottom - 1);
  1167.  
  1168.                     gi.xOffset = xmin;
  1169.                     gi.yOffset = ymin;
  1170.  
  1171.                     gs.xWin = xmax - xmin;
  1172.                     gs.yWin = ymax - ymin;
  1173.  
  1174.                     /* Now we _really_ want to resize */
  1175.                     gs_xWin = gs.xWin;  gs_yWin = gs.yWin;
  1176.                   }
  1177.                   fMouseDown= fFalse;
  1178.                   fResize= fTrue;
  1179.                   break;
  1180.  
  1181.                 case INTUITICKS:
  1182.                   /*if(!gs.nAnim)
  1183.                     ModifyIDCMP(w, (w->IDCMPFlags) & ~INTUITICKS);*/
  1184.                   break;
  1185.               }
  1186.             }
  1187.  
  1188.             if(gs.nAnim)
  1189.               break;
  1190.           }
  1191.         }
  1192. #endif /* !MUIGUI */
  1193.  
  1194.         if(key != '\0')
  1195.         {
  1196. #endif /* AMIGA */
  1197.  
  1198.  
  1199.           /*
  1200.            *  Handle keyboard input
  1201.            */
  1202.  
  1203. LSwitch:
  1204.           switch (key) {
  1205. #ifdef PCG
  1206.           case chNull:
  1207.             key = NFromAltN(getch());
  1208.             goto LSwitch;
  1209. #endif
  1210.           case ' ':
  1211.             fRedraw = fTrue;
  1212.             break;
  1213.           case 'p':
  1214.             not(fPause);
  1215.             break;
  1216.           case 'r':
  1217.             neg(dir);
  1218.             break;
  1219.           case 'x':
  1220.             not(gs.fInverse);
  1221.             InitColorsX();
  1222.             fRedraw = fTrue;
  1223.             break;
  1224.           case 'm':
  1225.             if (!gi.fMono)
  1226.             {
  1227.               not(gs.fColor);
  1228. #ifdef MSG
  1229.               _getvideoconfig((struct videoconfig far *) &gi.cfg);
  1230. #endif
  1231.               InitColorsX();
  1232.               fRedraw = fTrue;
  1233.             }
  1234.             break;
  1235.           case 'B':
  1236. #ifdef X11
  1237.             XSetWindowBackgroundPixmap(gi.disp, gi.root, gi.pmap);
  1238.             XClearWindow(gi.disp, gi.root);
  1239. #endif
  1240.  
  1241. #ifdef PCG
  1242.             gs.xWin = xPcScreen;
  1243.             gs.yWin = yPcScreen;
  1244.             SquareX(&gs.xWin, &gs.yWin, fFalse);
  1245.             fResize = fTrue;
  1246. #endif
  1247.             break;
  1248.           case 't':
  1249.             not(gs.fText);
  1250.             fRedraw = fTrue;
  1251.             break;
  1252.           case 'i':
  1253.             not(gs.fAlt);
  1254.             fRedraw = fTrue;
  1255.             break;
  1256.           case 'b':
  1257.             not(gs.fBorder);
  1258.             fRedraw = fTrue;
  1259.             break;
  1260.           case 'l':
  1261.             not(gs.fLabel);
  1262.             fRedraw = fTrue;
  1263.             break;
  1264.           case 'j':
  1265.             not(gs.fJetTrail);
  1266.             break;
  1267.           case '<':
  1268.             if (gs.nScale > 100) 
  1269.             {
  1270.               gs.nScale -= 100;
  1271.               fResize = fTrue;
  1272.             }
  1273.             break;
  1274.           case '>':
  1275.             if (gs.nScale < 400) 
  1276.             {
  1277.               gs.nScale += 100;
  1278.               fResize = fTrue;
  1279.             }
  1280.             break;
  1281.           case '[':
  1282.             if (gi.nMode == gGlobe && gs.rTilt > -rDegQuad)
  1283.             {
  1284.               gs.rTilt = gs.rTilt > -rDegQuad ? gs.rTilt-11.25 : -rDegQuad;
  1285.               fRedraw = fTrue;
  1286.             }
  1287.             break;
  1288.           case ']':
  1289.             if (gi.nMode == gGlobe && gs.rTilt < rDegQuad) 
  1290.             {
  1291.               gs.rTilt = gs.rTilt < rDegQuad ? gs.rTilt+11.25 : rDegQuad;
  1292.               fRedraw = fTrue;
  1293.             }
  1294.             break;
  1295.           case 'Q':
  1296.             SquareX(&gs.xWin, &gs.yWin, fTrue);
  1297.             fResize = fTrue;
  1298.             break;
  1299.           case 'R':
  1300.             for (i = oChi; i <= oVes; i++)
  1301.               not(ignore[i]);
  1302.             for (i = oLil; i <= oEP; i++)
  1303.               not(ignore[i]);
  1304.             fCast = fTrue;
  1305.             break;
  1306.           case 'C':
  1307.             not(us.fCusp);
  1308.             for (i = cuspLo; i <= cuspHi; i++)
  1309.               ignore[i] = !us.fCusp || !ignore[i];
  1310.             fCast = fTrue;
  1311.             break;
  1312.           case 'u':
  1313.             not(us.fUranian);
  1314.             for (i = uranLo; i <= uranHi; i++)
  1315.               ignore[i] = !us.fUranian || !ignore[i];
  1316.             fCast = fTrue;
  1317.             break;
  1318.           case 'U':
  1319.             us.nStar = !us.nStar;
  1320.             for (i = starLo; i <= starHi; i++)
  1321.               ignore[i] = !us.nStar || !ignore[i];
  1322.             fCast = fTrue;
  1323.             break;
  1324.           case 'c':
  1325.             if (!us.nRel)
  1326.             {
  1327.               us.nRel = rcDual;
  1328.               ciTwin = ciMain;
  1329.             }
  1330.             else us.nRel = 0;
  1331.             fCast = fTrue;
  1332.             break;
  1333.           case 's':
  1334.             not(us.fSiderial);
  1335.             fCast = fTrue;
  1336.             break;
  1337.           case 'h':
  1338.             us.objCenter = us.objCenter ? 0 : 1;
  1339.             fCast = fTrue;
  1340.             break;
  1341.           case 'f':
  1342.             not(us.fFlip);
  1343.             fCast = fTrue;
  1344.             break;
  1345.           case 'g':
  1346.             not(us.fDecan);
  1347.             fCast = fTrue;
  1348.             break;
  1349.           case '+':
  1350.             Animate(gs.nAnim, abs(dir));
  1351.             fCast = fTrue;
  1352.             break;
  1353.           case '-':
  1354.             Animate(gs.nAnim, -abs(dir));
  1355.             fCast = fTrue;
  1356.             break;
  1357.           case 'o':
  1358.             ciSave = ciMain;
  1359.             break;
  1360.           case 'O':
  1361.             ciMain = ciSave;
  1362.             fCast = fTrue;
  1363.             break;
  1364.  
  1365. #ifdef TIME
  1366.           case 'n':
  1367.             FInputData(szNowCore);
  1368.             ciMain = ciCore;
  1369.             fCast = fTrue;
  1370.             break;
  1371. #endif /* TIME */
  1372.  
  1373.           case 'N':                     /* The continuous update animation. */
  1374.             gs.nAnim = gs.nAnim ? 0 : -10;
  1375.             break;
  1376.  
  1377.           /* These are the nine different "add time to chart" animations. */
  1378.  
  1379.           case '!': gs.nAnim = -1; break;
  1380.           case '@': gs.nAnim = -2; break;
  1381.           case '#': gs.nAnim = -3; break;
  1382.           case '$': gs.nAnim = -4; break;
  1383.           case '%': gs.nAnim = -5; break;
  1384.           case '^': gs.nAnim = -6; break;
  1385.           case '&': gs.nAnim = -7; break;
  1386.           case '*': gs.nAnim = -8; break;
  1387.           case '(': gs.nAnim = -9; break;
  1388.  
  1389.           /* Should we go switch to a new chart type? */
  1390.  
  1391.           case 'V': gi.nMode = gWheel;      fRedraw = fTrue; break;
  1392.           case 'A': gi.nMode = gGrid;       fRedraw = fTrue; break;
  1393.           case 'Z': gi.nMode = gHorizon;    fRedraw = fTrue; break;
  1394.           case 'S': gi.nMode = gOrbit;      fRedraw = fTrue; break;
  1395.           case 'J': gi.nMode = gDisposit;   fRedraw = fTrue; break;
  1396.           case 'L': gi.nMode = gAstroGraph; fRedraw = fTrue; break;
  1397.           case 'K': gi.nMode = gCalendar;   fRedraw = fTrue; break;
  1398.           case 'E': gi.nMode = gEphemeris;  fRedraw = fTrue; break;
  1399.           case 'W': gi.nMode = gWorldMap;   fRedraw = fTrue; break;
  1400.           case 'G': gi.nMode = gGlobe;      fRedraw = fTrue; break;
  1401.           case 'P': gi.nMode = gPolar;      fRedraw = fTrue; break;
  1402.  
  1403. #ifdef BIORHYTHM
  1404.           case 'Y':            /* Should we switch to biorhythm chart? */
  1405.             if (!us.nRel)
  1406.               ciTwin = ciMain;
  1407.             us.nRel = rcBiorhythm;
  1408.             gi.nMode = gBiorhythm;
  1409.             fCast = fTrue;
  1410.             break;
  1411. #endif /* BIORHYTHM */
  1412.  
  1413.  
  1414. #ifdef CONSTEL
  1415.           case 'F':
  1416.             if (!fMap && gi.nMode != gGlobe && gi.nMode != gPolar)
  1417.               gi.nMode = gWorldMap;
  1418.             not(gs.fConstel);
  1419.             fRedraw = fTrue;
  1420.             break;
  1421. #endif /* CONSTEL */
  1422.  
  1423.           case '0':
  1424.             not(us.fPrimeVert);
  1425.             not(us.fCalendarYear);
  1426.             not(us.nEphemYears);
  1427.             not(gs.fMollewide);
  1428.             gi.nMode = (gi.nMode == gWheel ? gHouse :
  1429.                        (gi.nMode == gHouse ? gWheel : gi.nMode));
  1430.             fRedraw = fTrue;
  1431.             break;
  1432.           case 'v': case 'H': case '?':
  1433.  
  1434. #ifdef MSG
  1435.             _setvideomode(_DEFAULTMODE);
  1436.             if (key != 'v')
  1437.               _settextrows(50);
  1438. #endif /* MSG */
  1439.  
  1440. #ifdef BGI
  1441.             restorecrtmode();
  1442.             if (key != 'v')
  1443.               textmode(C4350);
  1444. #endif /* BGI */
  1445.  
  1446. #ifdef AMIGA
  1447.             /*ScreenToBack(gi.scr);*/
  1448.  
  1449.             /*EndX();*/
  1450.             AmigaClearScreen(); xPrintAt(1,1,"");
  1451. #endif /* AMIGA */
  1452.  
  1453.             length = us.nScrollRow;
  1454.             us.nScrollRow = 0;
  1455.             if (key == 'v')
  1456.               ChartListing();
  1457.             else
  1458.               DisplayKeysX();
  1459.             us.nScrollRow = length;
  1460.  
  1461. #ifdef PCG
  1462.             while (!kbhit())
  1463.               ;
  1464.             key = getch();
  1465.             if (key == 'q' || key == chEscape || key == chBreak)
  1466.             {
  1467.               fBreak = fTrue;
  1468.               break;
  1469.             }
  1470.             BeginX();
  1471.             fResize = fTrue;
  1472. #endif /* PCG */
  1473.  
  1474. #ifdef AMIGA
  1475.             /*key= getkey();*/
  1476.             AmigaDisplayUpdate(); key= AmigaGetKey();
  1477.  
  1478.             if(key == 'q' || key == chEscape || key == chBreak)
  1479.             {
  1480.               fBreak= fTrue;
  1481.               break;
  1482.             }
  1483.             /*ScreenToFront(gi.scr);*/
  1484.             /*BeginX();*/
  1485.             fResize= fTrue;
  1486. #endif /* AMIGA */
  1487.             break;
  1488.  
  1489.           case chReturn:
  1490.             CommandLineX();
  1491.             fResize = fCast = fTrue;
  1492.             break;
  1493.  
  1494. #ifdef PCG
  1495.           case chTab:
  1496.             if (gi.nRes == gs.nResHi)
  1497.               gi.nRes = gs.nResLo;
  1498.             else
  1499.               gi.nRes = gs.nResHi;
  1500.             BeginX();
  1501.             gs.xWin = xPcScreen;
  1502.             gs.yWin = yPcScreen;
  1503.             SquareX(&gs.xWin, &gs.yWin, fFalse);
  1504.             fResize = fTrue;
  1505.             break;
  1506. #endif /* PCG */
  1507.  
  1508. #ifdef AMIGA
  1509.           case chTab:
  1510.             key= AmigaDisplayDebug();
  1511.             if(key == 'q' || key == chEscape || key == chBreak)
  1512.               fBreak= fTrue;
  1513.             fResize = fCast = fTrue;
  1514.             break;
  1515. #endif
  1516.  
  1517.           case chDelete:
  1518.  
  1519. #ifdef PCG
  1520. #ifdef MOUSE
  1521.             MouseShow(fFalse);
  1522. #endif
  1523. #endif /* PCG */
  1524.  
  1525.             fT = gs.fJetTrail;
  1526.             gs.fJetTrail = fFalse;
  1527.             DrawClearScreen();
  1528.             gs.fJetTrail = fT;
  1529.             break;
  1530.  
  1531. #ifdef MOUSE
  1532.           case 'z'-'`': coldrw = kBlack;   break;
  1533.           case 'e'-'`': coldrw = kMaroon;  break;
  1534.           case 'f'-'`': coldrw = kDkGreen; break;
  1535.           case 'o'-'`': coldrw = kOrange;  break;
  1536.           case 'n'-'`': coldrw = kDkBlue;  break;
  1537.           case 'u'-'`': coldrw = kPurple;  break;
  1538.           case 'k'-'`': coldrw = kDkCyan;  break;
  1539.           case 'l'-'`': coldrw = kLtGray;  break;
  1540.           case 'd'-'`': coldrw = kDkGray;  break;
  1541.           case 'r'-'`': coldrw = kRed;     break;
  1542.           case 'g'-'`': coldrw = kGreen;   break;
  1543.           case 'y'-'`': coldrw = kYellow;  break;
  1544.           case 'b'-'`': coldrw = kBlue;    break;
  1545.           case 'v'-'`': coldrw = kMagenta; break;
  1546.           case 'j'-'`': coldrw = kCyan;    break;
  1547.           case 'a'-'`': coldrw = kWhite;   break;
  1548. #ifdef PCG
  1549.           case 't'-'`':
  1550.             MouseShow(fFalse);
  1551.             if (buttonx >= 0)
  1552. #ifdef MSG
  1553.               _rectangle(_GBORDER, buttonx, buttony, mousex, mousey);
  1554. #else
  1555.               DrawEdge(Min(buttonx, mousex) - gi.xOffset,
  1556.                        Min(buttony, mousey) - gi.yOffset,
  1557.                        Max(mousex, buttonx) - gi.xOffset,
  1558.                        Max(mousey, buttony) - gi.yOffset);
  1559. #endif /* MSG */
  1560.             MouseShow(fTrue);
  1561.             break;
  1562.           case 'x'-'`':
  1563.             MouseShow(fFalse);
  1564.             if (buttonx >= 0)
  1565.             {
  1566. #ifdef MSG
  1567.               _ellipse(_GBORDER, buttonx, buttony, mousex, mousey);
  1568. #else
  1569.               DrawEllipse(Min(buttonx, mousex) - gi.xOffset,
  1570.                           Min(buttony, mousey) - gi.yOffset,
  1571.                           Max(mousex, buttonx) - gi.xOffset,
  1572.                           Max(mousey, buttony) - gi.yOffset);
  1573. #endif /* MSG */
  1574.             }
  1575.             MouseShow(fTrue);
  1576.             break;
  1577. #endif /* PCG */
  1578. #endif /* MOUSE */
  1579.           case 'q': case chEscape: case chBreak:
  1580.             fBreak = fTrue;
  1581.             break;
  1582.           default:
  1583.             if (key > '0' && key <= '9')
  1584.             {
  1585. #ifdef PCG
  1586.               if (gs.nAnim && !fPause)
  1587. #endif /* PCG */
  1588.                 /* Process numbers 1..9 signifying animation rate. */
  1589.                 dir = (dir > 0 ? 1 : -1)*(key-'0');
  1590. #ifdef PCG
  1591.               else
  1592.               {
  1593.                 /* If we aren't in animation mode, then 1..9 refers to the */
  1594.                 /* clipping "quadrant" to use if chart size > screen size. */
  1595.  
  1596.                 xcorner = key-'0';
  1597.                 fResize = fTrue;
  1598.               }
  1599. #endif /* PCG */
  1600.  
  1601.               break;
  1602.             }
  1603.             else if (FBetween(key, 201, 248))
  1604.             {
  1605.               is.fSzInteract = fTrue;
  1606.               if (szMacro[key-201]) 
  1607.               {
  1608.                 FProcessCommandLine(szMacro[key-201]);
  1609.                 fResize = fCast = fTrue;
  1610.               }
  1611.               is.fSzInteract = fFalse;
  1612.               break;
  1613.             }
  1614.             putchar(chBell);    /* Any key not bound will sound a beep. */
  1615.           }  /* switch */
  1616.         }  /* if */
  1617.  
  1618. #ifdef X11
  1619.       default:
  1620.         ;
  1621.       }  /* switch */
  1622.     }  /* if */
  1623. #endif /* X11 */
  1624.  
  1625.   }  /* while */
  1626. }
  1627.  
  1628.  
  1629. /* This is called right before program termination to get rid of the window. */
  1630.  
  1631. void EndX()
  1632. {
  1633. #ifdef X11
  1634.   XFreeGC(gi.disp, gi.gc);
  1635.   XFreeGC(gi.disp, gi.pmgc);
  1636.   XFreePixmap(gi.disp, gi.pmap);
  1637.   XDestroyWindow(gi.disp, gi.wind);
  1638.   XCloseDisplay(gi.disp);
  1639. #endif
  1640.  
  1641. #ifdef MSG
  1642.   _setvideomode(_DEFAULTMODE);
  1643. #endif
  1644.  
  1645. #ifdef BGI
  1646.   restorecrtmode();
  1647. #endif
  1648.  
  1649. #ifdef AMIGA
  1650.   AmigaDisplayExit();
  1651. #endif
  1652.  
  1653. }
  1654. #endif /* ISG */
  1655.  
  1656.  
  1657. /*
  1658. ******************************************************************************
  1659. ** Main Graphics Processing.
  1660. ******************************************************************************
  1661. */
  1662.  
  1663. /* Process one command line switch passed to the program dealing with the    */
  1664. /* graphics features. This is just like the processing of each switch in the */
  1665. /* main program, however here each switch has been prefixed with an 'X'.     */
  1666.  
  1667. int NProcessSwitchesX(argc, argv, pos, fOr, fAnd, fNot)
  1668. int argc, pos;
  1669. bool fOr, fAnd, fNot;
  1670. char **argv;
  1671. {
  1672.   int darg = 0, i, j;
  1673.   real rT;
  1674.   char ch1;
  1675.  
  1676.   ch1 = argv[0][pos+1];
  1677.  
  1678.   switch (argv[0][pos]) {
  1679.  
  1680.   case chNull:
  1681.     break;
  1682.  
  1683.   case 'b':
  1684.     /*printf("--> `Xb' switch detected!\n");*/
  1685.     if (is.fSzInteract) 
  1686.     {
  1687.       ErrorArgv("Xb");
  1688.       return tcError;
  1689.     }
  1690.     ch1 = ChCap(ch1);
  1691.  
  1692.     if (FValidBmpmode(ch1))
  1693.       gs.chBmpMode = ch1;
  1694.  
  1695.     SwitchF2(gs.fBitmap);
  1696.     gs.fPS = gs.fMeta = fFalse;
  1697.     break;
  1698.  
  1699. #ifdef PS
  1700.   case 'p':
  1701.     if (is.fSzInteract)
  1702.     {
  1703.       ErrorArgv("Xp");
  1704.       return tcError;
  1705.     }
  1706.     gs.fPS = fTrue + (ch1 != '0');
  1707.     gs.fBitmap = gs.fMeta = fFalse;
  1708.     break;
  1709. #endif
  1710.  
  1711. #ifdef META
  1712.   case 'M':
  1713.     if (is.fSzInteract) 
  1714.     {
  1715.       ErrorArgv("XM");
  1716.       return tcError;
  1717.     }
  1718.     if (ch1 == '0')
  1719.       SwitchF(gs.fFont);
  1720.  
  1721.     SwitchF2(gs.fMeta);
  1722.     gs.fBitmap = gs.fPS = fFalse;
  1723.     break;
  1724. #endif
  1725.  
  1726.   case 'o':
  1727.     if (is.fSzInteract) 
  1728.     {
  1729.       ErrorArgv("Xo");
  1730.       return tcError;
  1731.     }
  1732.     if (argc <= 1)
  1733.     {
  1734.       ErrorArgc("Xo");
  1735.       return tcError;
  1736.     }
  1737.  
  1738.     if (!gs.fBitmap && !gs.fPS && !gs.fMeta)
  1739.       gs.fBitmap = fTrue;  /* default */
  1740.  
  1741.     gi.szFileOut = SzPersist(argv[1]);
  1742.     darg++;
  1743.     break;
  1744.  
  1745. #ifdef X11
  1746.   case 'B':
  1747.     if (is.fSzInteract) 
  1748.     {
  1749.       ErrorArgv("XB");
  1750.       return tcError;
  1751.     }
  1752.     SwitchF(gs.fRoot);
  1753.     break;
  1754. #endif
  1755.  
  1756.   case 'm':
  1757.     SwitchF(gs.fColor);
  1758.     break;
  1759.  
  1760.   case 'r':
  1761.     SwitchF(gs.fInverse);
  1762.     break;
  1763.  
  1764.   case 'w':
  1765.     if (argc <= 1) 
  1766.     {
  1767.       ErrorArgc("Xw");
  1768.       return tcError;
  1769.     }
  1770.  
  1771.     i = atoi(argv[1]);
  1772.  
  1773.     if (argc > 2 && ((j = atoi(argv[2])) || argv[2][0] == '0'))
  1774.     {
  1775.       argc--; argv++;
  1776.       darg++;
  1777.     }
  1778.     else j = i;
  1779.  
  1780.     if (!FValidGraphx(i))
  1781.     {
  1782.       ErrorValN("Xw", i);
  1783.       return tcError;
  1784.     }
  1785.     if (!FValidGraphy(j)) 
  1786.     {
  1787.       ErrorValN("Xw", j);
  1788.       return tcError;
  1789.     }
  1790.     gs.xWin = i; gs.yWin = j;
  1791.     darg++;
  1792.     break;
  1793.  
  1794.   case 's':
  1795.     if (argc <= 1)
  1796.     {
  1797.       ErrorArgc("Xs");
  1798.       return tcError;
  1799.     }
  1800.     i = atoi(argv[1]);
  1801.     if (i < 100)
  1802.       i *= 100;
  1803.  
  1804.     if (!FValidScale(i))
  1805.     {
  1806.       ErrorValN("Xs", i);
  1807.       return tcError;
  1808.     }
  1809.     gs.nScale = i;
  1810.     darg++;
  1811.     break;
  1812.  
  1813.   case 'i':
  1814.     SwitchF(gs.fAlt);
  1815.     break;
  1816.  
  1817.   case 't':
  1818.     SwitchF(gs.fText);
  1819.     break;
  1820.  
  1821.   case 'u':
  1822.     SwitchF(gs.fBorder);
  1823.     break;
  1824.  
  1825.   case 'l':
  1826.     SwitchF(gs.fLabel);
  1827.     break;
  1828.  
  1829.   case 'j':
  1830.     SwitchF(gs.fJetTrail);
  1831.     break;
  1832.  
  1833.   case '1':
  1834.     if (argc <= 1) 
  1835.     {
  1836.       ErrorArgc("X1");
  1837.       return tcError;
  1838.     }
  1839.     i = atoi(argv[1]);
  1840.     if (!FItem(i)) 
  1841.     {
  1842.       ErrorValN("X1", i);
  1843.       return tcError;
  1844.     }
  1845.     gs.nLeft = i;
  1846.     darg++;
  1847.     break;
  1848.  
  1849.   case '2':
  1850.     if (argc <= 1) 
  1851.     {
  1852.       ErrorArgc("X2");
  1853.       return tcError;
  1854.     }
  1855.     i = atoi(argv[1]);
  1856.     if (!FItem(i)) {
  1857.       ErrorValN("X2", i);
  1858.       return tcError;
  1859.     }
  1860.     gs.nLeft = -i;
  1861.     darg++;
  1862.     break;
  1863.  
  1864.   case 'd':
  1865.     if (is.fSzInteract) 
  1866.     {
  1867.       ErrorArgv("Xd");
  1868.       return tcError;
  1869.     }
  1870.     if (argc <= 1) 
  1871.     {
  1872.       ErrorArgc("Xd");
  1873.       return tcError;
  1874.     }
  1875.     gs.szDisplay = SzPersist(argv[1]);
  1876.     darg++;
  1877.     break;
  1878.  
  1879.   case 'W':
  1880.     if (argc > 1 && ((i = atoi(argv[1])) || argv[1][0] == '0')) 
  1881.     {
  1882.       darg++;
  1883.       if (!FValidRotation(i)) 
  1884.       {
  1885.         ErrorValN("XW", i);
  1886.         return tcError;
  1887.       }
  1888.       gs.nRot = i;
  1889.     }
  1890.     gi.nMode = gWorldMap;
  1891.     if (ch1 == '0')
  1892.       gs.fMollewide = fTrue;
  1893.     is.fHaveInfo = fTrue;
  1894.     break;
  1895.  
  1896.   case 'G':
  1897.     if (argc > 1 && ((i = atoi(argv[1])) || argv[1][0] == '0')) 
  1898.     {
  1899.       darg++;
  1900.       if (!FValidRotation(i)) 
  1901.       {
  1902.         ErrorValN("XG", i);
  1903.         return tcError;
  1904.       }
  1905.       gs.nRot = i;
  1906.       if (argc > 2 && ((rT = atof(argv[2])) || argv[2][0] == '0')) 
  1907.       {
  1908.         darg++;
  1909.         if (!FValidTilt(rT)) 
  1910.         {
  1911.           ErrorValR("XG", rT);
  1912.           return tcError;
  1913.         }
  1914.         gs.rTilt = rT;
  1915.       }
  1916.     }
  1917.     gi.nMode = gGlobe;
  1918.     is.fHaveInfo = fTrue;
  1919.     break;
  1920.  
  1921.   case 'P':
  1922.     if(argc > 1 && ((i = atoi(argv[1])) || argv[1][0] == '0'))
  1923.     {
  1924.       darg++;
  1925.       if (!FValidRotation(i))
  1926.       {
  1927.         ErrorValN("XP", i);
  1928.         return tcError;
  1929.       }
  1930.     } 
  1931.     else i = 0;
  1932.     gs.nRot = i;
  1933.     gi.nMode = gPolar;
  1934.     if (ch1 == '0')
  1935.       gs.fPrintMap = fTrue;
  1936.     is.fHaveInfo = fTrue;
  1937.     break;
  1938.  
  1939. #ifdef CONSTEL
  1940.   case 'F':
  1941.     if (!fMap && gi.nMode != gGlobe && gi.nMode != gPolar)
  1942.       gi.nMode = gWorldMap;
  1943.     not(gs.fConstel);
  1944.     is.fHaveInfo = fTrue;
  1945.     break;
  1946. #endif
  1947.  
  1948. #ifdef ISG
  1949.   case 'n':
  1950.     if (argc > 1 && (i = atoi(argv[1])))
  1951.       darg++;
  1952.     else
  1953.       i = 10;
  1954.     if (i < 1 || i > 10) 
  1955.     {
  1956.       ErrorValN("Xn", i);
  1957.       return tcError;
  1958.     }
  1959.     gs.nAnim = i;
  1960.     break;
  1961. #endif
  1962.  
  1963.   default:
  1964.     ErrorSwitch(argv[0]);
  1965.     return tcError;
  1966.   }
  1967.   /* 'darg' contains the value to be added to argc when we return. */
  1968.   return darg;
  1969. }
  1970.  
  1971.  
  1972. /* Process one command line switch passed to the program dealing with more  */
  1973. /* obscure graphics options. This is structured very much like the function */
  1974. /* NProcessSwitchesX(), except here we know each switch begins with 'YX'.   */
  1975.  
  1976. int NProcessSwitchesRareX(argc, argv, pos)
  1977. int argc, pos;
  1978. char **argv;
  1979. {
  1980.   int darg = 0, i, j;
  1981.   char ch1;
  1982.  
  1983.   ch1 = argv[0][pos+1];
  1984.   switch (argv[0][pos]) {
  1985.  
  1986.   case chNull:
  1987.     if (argc <= 2)
  1988.     {
  1989.       ErrorArgc("YX");
  1990.       return tcError;
  1991.     }
  1992. #ifdef PCG
  1993.     i = atoi(argv[1]);
  1994.     if (!FValidResmode(i))
  1995.     {
  1996.       ErrorValN("YX", i);
  1997.       return tcError;
  1998.     }
  1999.     gs.nResHi = i;
  2000.     i = atoi(argv[2]);
  2001.  
  2002.     if (!FValidResmode(i)) 
  2003.     {
  2004.       ErrorValN("YX", i);
  2005.       return tcError;
  2006.     }
  2007.     gs.nResLo = i;
  2008.     gs.fBitmap = gs.fPS = gs.fMeta = fFalse;
  2009. #endif
  2010.  
  2011.     darg += 2;
  2012.     break;
  2013.  
  2014.   case 'G':
  2015.     if (argc <= 1) 
  2016.     {
  2017.       ErrorArgc("YXG");
  2018.       return tcError;
  2019.     }
  2020.     i = atoi(argv[1]);
  2021.     if (!FValidGlyphs(i))
  2022.     {
  2023.       ErrorValN("YXg", i);
  2024.       return tcError;
  2025.     }
  2026.     gs.nGlyphs = i;
  2027.     j = i/1000;
  2028.     if (FBetween(j, 1, 2))
  2029.       szDrawSign[sCap] = szDrawSign[cSign+j];
  2030.     j = (i/100)%10;
  2031.     if (FBetween(j, 1, 2))
  2032.       szDrawObject[oUra] = szDrawObject[oNorm+j];
  2033.     j = (i/10)%10;
  2034.     if (FBetween(j, 1, 2))
  2035.       szDrawObject[oPlu] = szDrawObject[oNorm+2+j];
  2036.     j = i%10;
  2037.     if (FBetween(j, 1, 3))
  2038.       szDrawObject[oLil] = szDrawObject[oNorm+4+j];
  2039.     darg++;
  2040.     break;
  2041.  
  2042.   case 'g':
  2043.     if (argc <= 1)  
  2044.     {
  2045.       ErrorArgc("YXg");
  2046.       return tcError;
  2047.     }
  2048.     i = atoi(argv[1]);
  2049.     if (!FValidGrid(i)) 
  2050.     {
  2051.       ErrorValN("YXg", i);
  2052.       return tcError;
  2053.     }
  2054.     gs.nGridCell = i;
  2055.     darg++;
  2056.     break;
  2057.  
  2058.   case 'f':
  2059.     if (argc <= 1) 
  2060.     {
  2061.       ErrorArgc("YXf");
  2062.       return tcError;
  2063.     }
  2064.     gs.fFont = atoi(argv[1]);
  2065.     darg++;
  2066.     break;
  2067.  
  2068. #ifdef PS
  2069.   case 'p':
  2070.     if (ch1 == '0') 
  2071.     {
  2072.       if (argc <= 2) 
  2073.       {
  2074.         ErrorArgc("YXp0");
  2075.         return tcError;
  2076.       }
  2077.       gs.xInch = atof(argv[1]);
  2078.       gs.yInch = atof(argv[2]);
  2079.       darg += 2;
  2080.       break;
  2081.     }
  2082.     if (argc <= 1)
  2083.     {
  2084.       ErrorArgc("YXp");
  2085.       return tcError;
  2086.     }
  2087.     gs.nOrient = atoi(argv[1]);
  2088.     darg++;
  2089.     break;
  2090. #endif
  2091.  
  2092.   default:
  2093.     ErrorSwitch(argv[0]);
  2094.     return tcError;
  2095.   }
  2096.   /* 'darg' contains the value to be added to argc when we return. */
  2097.   return darg;
  2098. }
  2099.  
  2100.  
  2101. /* This is the main interface to all the graphics features. This routine     */
  2102. /* is called from the main program if any of the -X switches were specified, */
  2103. /* and it sets up for and goes and generates the appropriate graphics chart. */
  2104. /* We return fTrue if successfull, fFalse if some non-fatal error occurred.  */
  2105.  
  2106. bool FActionX()
  2107. {
  2108.   int i;
  2109.  
  2110.   /* Set up variables in preparation for graphics. Set the glyphs for     */
  2111.   /* certain objects to point to their current setting, and if doing      */
  2112.   /* constellations, give a couple stars more correct astronomical names. */
  2113.  
  2114. #ifdef CONSTEL
  2115.   if (gs.fConstel)
  2116.   {
  2117.     szObjName[starLo-1+10] = "Alnilam";  /* Normally "Orion"     */
  2118.     szObjName[starLo-1+47] = "M31";      /* Normally "Andromeda" */
  2119.   }
  2120. #endif
  2121.  
  2122.   i = gs.nGlyphs/1000;
  2123.   szDrawSign[sCap] = szDrawSign[cSign+(i == 2 ? 2 : 1)];
  2124.  
  2125.   i = (gs.nGlyphs/100)%10;
  2126.   szDrawObject[oUra] = szDrawObject[oNorm+(i == 2 ? 2 : 1)];
  2127.  
  2128.   i = (gs.nGlyphs/10)%10;
  2129.   szDrawObject[oPlu] = szDrawObject[oNorm+2+(i == 2 ? 2 : 1)];
  2130.  
  2131.   i = gs.nGlyphs%10;
  2132.   szDrawObject[oLil] = szDrawObject[oNorm+4+(FBetween(i, 2, 3) ? i : fSouthNode ? 3 : 1)];
  2133.  
  2134.   if (fSouthNode)
  2135.     szObjectFont[oSou] = '>';
  2136.  
  2137.   /*printf("fBitmap=%d  fPS=%d  fMeta=%d\n", gs.fBitmap, gs.fPS, gs.fMeta);*/
  2138.   gi.fFile = (gs.fBitmap || gs.fPS || gs.fMeta) /*& 0*/;
  2139.  
  2140. #ifdef PS
  2141.   gi.fEps = gs.fPS > fTrue;
  2142. #endif
  2143.  
  2144.   /* First figure out what graphic mode to generate the chart in, based on */
  2145.   /* various non-X command switches, e.g. -L combined with -X, -g combined */
  2146.   /* with -X, and so on, and determine the size the window is to be, too.  */
  2147.  
  2148.   if (gi.nMode == gWheel) 
  2149.   {
  2150.     if (us.fWheel)
  2151.       gi.nMode = gHouse;
  2152.  
  2153.     else if (us.fGrid || us.fMidpoint)
  2154.     {
  2155.       gi.nMode = gGrid;
  2156.  
  2157.       if (us.nRel <= rcDual && us.fMidpoint && !us.fAspList)
  2158.         us.fGridConfig = fTrue;
  2159.  
  2160.       gs.xWin = gs.yWin = (gs.nGridCell + (us.nRel <= rcDual))*CELLSIZE*gi.nScale + 1;
  2161.     }
  2162.  
  2163.     else if (us.fHorizon)             gi.nMode = gHorizon;
  2164.     else if (us.fOrbit)               gi.nMode = gOrbit;
  2165.     else if (us.fInfluence)           gi.nMode = gDisposit;
  2166.     else if (us.fAstroGraph)          gi.nMode = gAstroGraph;
  2167.     else if (us.fCalendar)            gi.nMode = gCalendar;
  2168.     else if (us.fEphemeris)           gi.nMode = gEphemeris;
  2169.     else if (us.nRel == rcBiorhythm)  gi.nMode = gBiorhythm;
  2170.   }
  2171.  
  2172.   if (fMap) 
  2173.   {
  2174.     gs.xWin = nDegMax*gi.nScale;
  2175.     gs.yWin = nDegHalf*gi.nScale;
  2176.   }
  2177.  
  2178.   gi.nScaleT = gs.fPS ? PSMUL : (gs.fMeta ? METAMUL : 1);
  2179.  
  2180.   if (gi.fFile)
  2181.   {
  2182.     if (gs.xWin == 0)       gs.xWin  = DEFAULTX;
  2183.     if (gs.yWin == 0)       gs.yWin  = DEFAULTY;
  2184.     if (fSidebar)           gs.xWin += SIDESIZE;
  2185.     if (gs.xWin > BITMAPX)  gs.xWin  = BITMAPX;
  2186.     if (gs.yWin > BITMAPY)  gs.yWin  = BITMAPY;
  2187.  
  2188.     BeginFileX();
  2189.  
  2190.     if (gs.fBitmap) 
  2191.     {
  2192.       gi.cbBmpRow = (gs.xWin + 1) >> 1;
  2193.       gi.yBand = gs.yWin;
  2194.  
  2195.       if (!FEnsureGrid())
  2196.         return fFalse;
  2197.  
  2198.       while ((gi.bm = PAllocate((long)gi.cbBmpRow * gi.yBand, fTrue, NULL)) == NULL) 
  2199.       {
  2200.         PrintWarning("The bitmap must be generated in multiple stages.");
  2201.         gi.yBand = (gi.yBand + 1) / 2;
  2202.         if (gi.yBand < 1 || gs.chBmpMode != 'B')
  2203.           return fFalse;
  2204.       }
  2205.  
  2206.       if (gi.yBand == gs.yWin)
  2207.         gi.yBand = 0;
  2208.       else 
  2209.       {
  2210.         gi.yOffset = gs.yWin - gs.yWin % gi.yBand;
  2211.         if (gi.yOffset == gs.yWin)
  2212.           gi.yOffset -= gi.yBand;
  2213.       }
  2214.     }
  2215.  
  2216. #ifdef PS
  2217.     else if (gs.fPS)
  2218.       PsBegin();
  2219. #endif /* PS */
  2220.  
  2221. #ifdef META
  2222.     else
  2223.     {
  2224.       if (!FEnsureGrid())
  2225.         return fFalse;
  2226.       for (gi.cbMeta = MAXMETA;
  2227.            gi.cbMeta > 0 && (gi.bm = PAllocate(gi.cbMeta, fTrue, NULL)) == NULL;
  2228.            gi.cbMeta -= MAXMETA/8)
  2229.  
  2230.         PrintWarning("Attempting to get maximum memory for metafile.");
  2231.  
  2232.       if (gi.cbMeta == 0)
  2233.         return fFalse;
  2234.  
  2235.       gs.xWin   *= METAMUL;  /* Increase chart sizes and scales behind the */
  2236.       gs.yWin   *= METAMUL;  /* scenes to make graphics look smoother.     */
  2237.       gs.nScale *= METAMUL;
  2238.     }
  2239. #endif /* META */
  2240.     InitColorsX();
  2241.   }
  2242. #ifdef ISG
  2243.   else /* !gi.fFile */
  2244.   {
  2245.  
  2246. #ifdef PCG
  2247.     BeginX();
  2248.     if (gs.xWin == 0 || gs.yWin == 0)
  2249.     {
  2250.       if (gs.xWin == 0)  gs.xWin = xPcScreen;
  2251.       if (gs.yWin == 0)  gs.yWin = yPcScreen;
  2252.       SquareX(&gs.xWin, &gs.yWin, fFalse);
  2253.     } 
  2254.     else if(fSidebar)
  2255.       gs.xWin += SIDESIZE;
  2256.  
  2257. #else /* !PCG */
  2258.     if (gs.xWin == 0 || gs.yWin == 0)
  2259.     {
  2260.       if (gs.xWin == 0)  gs.xWin = DEFAULTX;
  2261.       if (gs.yWin == 0)  gs.yWin = DEFAULTY;
  2262.       SquareX(&gs.xWin, &gs.yWin, fFalse);
  2263.     }
  2264.     else if (fSidebar)
  2265.       gs.xWin += SIDESIZE;
  2266.     BeginX();
  2267. #endif /* PCG */
  2268.  
  2269.   }
  2270. #endif /* ISG */
  2271.  
  2272.   if (gi.fFile || gs.fRoot)    /* Go draw the graphic chart. */
  2273.     DrawChartX();
  2274.  
  2275.   if (gi.fFile)      /* Write bitmap to file if in that mode. */
  2276.   {
  2277.     EndFileX();
  2278.  
  2279.     while (gi.yBand)
  2280.     {
  2281.       gi.yOffset -= gi.yBand;
  2282.       DrawChartX();
  2283.       EndFileX();
  2284.     }
  2285.  
  2286.     if (!gs.fPS)
  2287.       DeallocateHuge(gi.bm);
  2288.   }
  2289. #ifdef ISG
  2290.  
  2291.   else /* !gi.fFile */
  2292.   {
  2293.  
  2294. #ifdef X11
  2295.     if (gs.fRoot)  /* Process -XB. */
  2296.     {
  2297.       XSetWindowBackgroundPixmap(gi.disp, gi.root, gi.pmap);
  2298.       XClearWindow(gi.disp, gi.root);
  2299.  
  2300.       /* If -Xn in effect with -XB, then enter infinite loop where we */
  2301.       /* calculate and animate chart, displaying on the root window.  */
  2302.  
  2303.       while (gs.nAnim)
  2304.       {
  2305.         Animate(gs.nAnim, 1);
  2306.         if (!gs.fJetTrail)
  2307.           XFillRectangle(gi.disp, gi.pmap, gi.pmgc, 0, 0, gs.xWin, gs.yWin);
  2308.         DrawChartX();
  2309.         XSetWindowBackgroundPixmap(gi.disp, gi.root, gi.pmap);
  2310.         XClearWindow(gi.disp, gi.root);
  2311.       }
  2312.     }
  2313.     else
  2314. #endif /* X11 */
  2315.  
  2316.       InteractX();    /* Window's up; process commands given to window now. */
  2317.     EndX();
  2318.   }
  2319. #endif /* ISG */
  2320.  
  2321.   return fTrue;
  2322. }
  2323. #endif /* GRAPH */
  2324.  
  2325. /* xscreen.c */
  2326.